package com.joysuch.wwyt.datadump.biz.service;

import cn.zlg.common.datadump.annotation.DataDumpEntity;
import cn.zlg.common.datadump.bean.BatchDeleteResult;
import cn.zlg.common.util.CollectionUtils;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.joysuch.wwyt.bp.entity.contractor.dsl.QBpContractor;
import com.joysuch.wwyt.bp.entity.contractor.dsl.QBpContractorStaff;
import com.joysuch.wwyt.bp.entity.dsl.*;
import com.joysuch.wwyt.bp.entity.inspect.dsl.QBPInspectItem;
import com.joysuch.wwyt.bp.repository.BPNFCLocationDao;
import com.joysuch.wwyt.bp.repository.BpContractorStaffDao;
import com.joysuch.wwyt.bp.service.*;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.entity.dsl.QBaseUser;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.exception.ApiBusinessException;
import com.joysuch.wwyt.core.exception.BusinessRestrictionsException;
import com.joysuch.wwyt.core.service.BaseUserService;
import com.joysuch.wwyt.datadump.biz.model.*;
import com.joysuch.wwyt.edu.entity.dsl.QEduCertificateUser;
import com.joysuch.wwyt.edu.entity.dsl.QEduQuestion;
import com.joysuch.wwyt.edu.service.EduCertificateService;
import com.joysuch.wwyt.edu.service.EduQuestionService;
import com.joysuch.wwyt.mh.bean.vo.MajorHazardDeleteCheckVO;
import com.joysuch.wwyt.mh.entity.dsl.QMhMajorHazard;
import com.joysuch.wwyt.mh.entity.dsl.QMhMajorHazardChemProduct;
import com.joysuch.wwyt.mh.entity.dsl.QMhMonitoringPoint;
import com.joysuch.wwyt.mh.service.MhHazardChemicalProductService;
import com.joysuch.wwyt.mh.service.MhMajorHazardService;
import com.joysuch.wwyt.mh.service.MhMonitoringPointService;
import com.joysuch.wwyt.monitoringcenter.service.LocateServerService;
import com.joysuch.wwyt.risk.entity.dsl.QRiskDistrict;
import com.joysuch.wwyt.risk.entity.vo.DistrictDeleteCheckVO;
import com.joysuch.wwyt.risk.service.RiskDistrictService;
import com.mysema.commons.lang.Assert;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.dsl.EntityPathBase;
import com.querydsl.core.types.dsl.SimpleExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

@Service
@Order(10)
@Primary
public class BatchDeleteService implements ApplicationContextAware, cn.zlg.common.datadump.service.BatchDeleteService {

    private static final Logger logger = LoggerFactory.getLogger(BatchDeleteService.class);

    private ApplicationContext applicationContext;

    @Autowired
    private JPAQueryFactory queryFactory;

    @Autowired
    private LocateServerService locateServerService;
    @Autowired
    private BpContractorService bpContractorService;
    @Autowired
    private RiskDistrictService riskDistrictService;
    @Autowired
    private BpNFCLocationService nfcLocationService;

    @Override
    public BatchDeleteResult batchDelete(Class entity, List<Long> ids) throws Exception {
        if (ids == null || ids.size() == 0) {
            return new BatchDeleteResult();
        }
        BatchDeleteResult r = new BatchDeleteResult();
        r.setTotal(ids.size());
        r.setCode(-1);
        DataDumpEntity entityAnnotation = (DataDumpEntity) entity.getAnnotation(DataDumpEntity.class);
        Assert.notNull(entityAnnotation,
                String.format("类%s没有%s注解,无法解析", entity.getName(), DataDumpEntity.class.getSimpleName()));
        int count = 0;
        try {
            BatchDeleteResult result = delete(entity, ids);
            if (result != null) {
                return result;
            }
        } catch (Exception e) {
            logger.error("批量删除【{}】出错,ids={}",entityAnnotation.businessName(), ids, e);
            return BatchDeleteResult.create(ids.size(), 0, Arrays.asList(e.getMessage()));
        }
        List<DistrictDeleteCheckVO> districtDeleteCheckVOS = Lists.newArrayList();
        List<MajorHazardDeleteCheckVO> majorHazardDeleteCheckVOS = Lists.newArrayList();
        for (Long id : ids) {
            try {
                DeleteWrapper dw = delete(entity, id);
                count += dw.count;
                if (dw.code == Status.DELETE_CHECK_FAILED.getCode() && StringUtils.isNotEmpty(dw.msg)) {
                    if (entity == RiskDistrictDumpBean.class) {
                        DistrictDeleteCheckVO vo = JSONObject.parseObject(dw.msg, DistrictDeleteCheckVO.class);
                        if (vo != null) {
                            districtDeleteCheckVOS.add(vo);
                        }
                    }
                    if (entity == MhMajorHazardDumpBean.class) {
                        MajorHazardDeleteCheckVO vo = JSONObject.parseObject(dw.msg, MajorHazardDeleteCheckVO.class);
                        if (vo != null) {
                            majorHazardDeleteCheckVOS.add(vo);
                        }
                    }
                } else {
                    if (dw.msg != null) {
                        String tag = getEntityTag(entity, id);
                        r.addError(tag + " : " + dw.msg);
                    }
                }
            } catch (Exception e) {
                String tag = getEntityTag(entity, id);
                r.addError(tag + " : " + e.getMessage());
            }
        }
        r.setSuccess(count);
        // 双预防-删除校验
        if (CollectionUtils.isNotEmpty(districtDeleteCheckVOS)) {
            r.setData(districtDeleteCheckVOS);
            r.setCode(Status.DELETE_CHECK_FAILED.getCode());
        }
        // 重大危险源-删除校验
        if (CollectionUtils.isNotEmpty(majorHazardDeleteCheckVOS)) {
            r.setData(majorHazardDeleteCheckVOS);
            r.setCode(Status.DELETE_CHECK_FAILED.getCode());
        }
        return r;
    }

    private String getEntityTag(Class entity, Long id) {
        if (entity == BaseUserDumpBean.class) {
            QBaseUser q = QBaseUser.baseUser;
            return getProperty(q, q.realName, q.id, id);
        } else if (entity == BpDepartDumpBean.class) {
            QBpDepart q = QBpDepart.bpDepart1;
            return getProperty(q, q.name, q.id, id);
        } else if (entity == BpJobDumpBean.class) {
            QBpJob q = QBpJob.bpJob;
            return getProperty(q, q.name, q.id, id);
        } else if (entity == BpContractorDumpBean.class) {
            QBpContractor q = QBpContractor.bpContractor;
            return getProperty(q, q.companyName, q.id, id);
        } else if (entity == BpContractorStaffDumpBean.class) {
            QBpContractorStaff q = QBpContractorStaff.bpContractorStaff;
            return getProperty(q, q.name, q.id, id);
        } else if (entity == BpIndustrialPipelineDumpBean.class) {
            QBpIndustrialPipeline q = QBpIndustrialPipeline.bpIndustrialPipeline;
            return getProperty(q, q.code, q.id, id);
        } else if (entity == BpInspectItemDumpBean.class) {
            QBPInspectItem q = QBPInspectItem.bPInspectItem;
            return getProperty(q, q.inspectItem, q.id, id);
        } else if (entity == BpInvestigateStoreDetailDumpBean.class) {
//            QBpInvestigateStoreDetail q = QBpInvestigateStoreDetail.bpInvestigateStoreDetail;
//            return getProperty(q, q.content, q.id, id);
            return "序号=" + id +": ";
        } else if (entity == BpNfcLocationDumpBean.class) {
            QBPNFCLocation q = QBPNFCLocation.BPNFCLocation;
            return getProperty(q, q.code, q.id, id);
        } else if (entity == BpProductFacilityDumpBean.class) {
            QBpProductionFacility q = QBpProductionFacility.bpProductionFacility;
            return getProperty(q, q.code, q.id, id);
        } else if (entity == BpStorageTankAreaService.class) {
            QBpStorageTankArea q = QBpStorageTankArea.bpStorageTankArea;
            return getProperty(q, q.name, q.id, id);
        } else if (entity == BpStorageTankDumpBean.class) {
            QBpStorageTank q = QBpStorageTank.bpStorageTank;
            return getProperty(q, q.name, q.id, id);
        } else if (entity == BpSystemVideoDumpBean.class) {
            QBpSystemVideo q = QBpSystemVideo.bpSystemVideo;
            return getProperty(q, q.name, q.id, id);
        } else if (entity == EduCertificateUserDumpBean.class) {
            QEduCertificateUser q = QEduCertificateUser.eduCertificateUser;
            return getProperty(q, q.certNo, q.id, id);
        } else if (entity == MhChemProductDumpBean.class) {
            QMhMajorHazardChemProduct q = QMhMajorHazardChemProduct.mhMajorHazardChemProduct;
            return getProperty(q, q.name, q.id, id);
        } else if (entity == MhMajorHazardDumpBean.class) {
            QMhMajorHazard q = QMhMajorHazard.mhMajorHazard;
            return getProperty(q, q.code, q.id, id);
        } else if (entity == MhMonitorPointDumpBean.class) {
            QMhMonitoringPoint q = QMhMonitoringPoint.mhMonitoringPoint;
            return getProperty(q, q.name, q.id, id);
        } else if (entity == RiskDistrictDumpBean.class) {
            QRiskDistrict q = QRiskDistrict.riskDistrict;
            return getProperty(q, q.code, q.id, id);
        } else if (entity == EduQuestionDumpBean.class) {
            QEduQuestion q = QEduQuestion.eduQuestion;
            return getProperty(q, q.name, q.id, id);
        } else {
            return "id=" + id;
        }
    }

    String  getProperty(EntityPathBase entity, Path p, SimpleExpression<Long> idPath, Long id) {
        Object first = ((JPAQuery) queryFactory.select(p).from(entity).where(idPath.eq(id))).fetchFirst();
        if(first == null) {
            return null;
        }
        if(first instanceof Tuple) {
            return String.valueOf(((Tuple) first).get(p));
        }
        return String.valueOf(first);
    }

    @Transactional
    protected BatchDeleteResult delete(Class defClass, List<Long> ids) {
        if (defClass.equals(BaseUserDumpBean.class)) {
            return BatchDeleteResult.create(ids.size(), locateServerService.batchUserDelete(ids));
        } else if (defClass.equals(BpContractorStaffDumpBean.class)) {
            return BatchDeleteResult.create(ids.size(), locateServerService.batchStaffDelete(ids));
        } else if (defClass.equals(BpNfcLocationDumpBean.class)) {
            return nfcLocationService.batchNfcDelate(ids);
        }
        return null;
    }

    @Transactional
    protected DeleteWrapper delete(Class entity, Long id) throws BusinessRestrictionsException {
        if (entity == BaseUserDumpBean.class) {
            applicationContext.getBean(BaseUserService.class).delete(id);
        } else if (entity == BpDepartDumpBean.class) {
            try {
                applicationContext.getBean(BpDepartService.class).delete(id);
            } catch (ApiBusinessException e) {
                e.printStackTrace();
            }
        } else if (entity == BpJobDumpBean.class) {
            applicationContext.getBean(BpJobService.class).delete(id);
        } else if (entity == BpContractorDumpBean.class) {
            bpContractorService.nullify(id);
        } else if (entity == BpContractorStaffDumpBean.class) {
            applicationContext.getBean(BpContractorStaffDao.class).deleteById(id);
        } else if (entity == BpIndustrialPipelineDumpBean.class) {
            applicationContext.getBean(BpIndustrialPipelineService.class).delete(id);
        } else if (entity == BpInspectItemDumpBean.class) {
            applicationContext.getBean(BPInspectItemService.class).deleteById(id);
        } else if (entity == BpInvestigateStoreDetailDumpBean.class) {
            ResultBean result = applicationContext.getBean(BpInvestigateStoreDetailService.class).delete(id);
            if (result.getCode() == 0) {
                return NORMAL;
            }
            return new DeleteWrapper(0, result.getMsg());
        } else if (entity == BpNfcLocationDumpBean.class) {
            applicationContext.getBean(BPNFCLocationDao.class).deleteById(id);
        } else if (entity == BpProductFacilityDumpBean.class) {
            applicationContext.getBean(BpProductionFacilityService.class).delete(id);
        } else if (entity == BpStorageTankAreaService.class) {
            applicationContext.getBean(BpStorageTankAreaService.class).delete(id);
        } else if (entity == BpStorageTankDumpBean.class) {
            applicationContext.getBean(BpStorageTankService.class).delete(id);
        } else if (entity == BpSystemVideoDumpBean.class) {
            applicationContext.getBean(BpSystemVideoService.class).delete(id);
        } else if (entity == EduCertificateUserDumpBean.class) {
            applicationContext.getBean(EduCertificateService.class).delete(id);
        } else if (entity == MhChemProductDumpBean.class) {
            applicationContext.getBean(MhHazardChemicalProductService.class).delete(id);
        } else if (entity == MhMajorHazardDumpBean.class) {
            try {
                applicationContext.getBean(MhMajorHazardService.class).delete(id);
            } catch (ApiBusinessException e) {
                if (e.getCode() == Status.DELETE_CHECK_FAILED.getCode() && StringUtils.isNotEmpty(e.getMessage())) {
                    return new DeleteWrapper(0, Status.DELETE_CHECK_FAILED.getCode(), e.getMessage());
                }
            }
        } else if (entity == MhMonitorPointDumpBean.class) {
            applicationContext.getBean(MhMonitoringPointService.class).deleteById(id);
        } else if (entity == RiskDistrictDumpBean.class) {
            try {
                riskDistrictService.delete(id);
            } catch (ApiBusinessException e) {
                if (e.getCode() == Status.DELETE_CHECK_FAILED.getCode() && StringUtils.isNotEmpty(e.getMessage())) {
                    return new DeleteWrapper(0, Status.DELETE_CHECK_FAILED.getCode(), e.getMessage());
                }
            }
        } else if (entity == EduQuestionDumpBean.class) {
            applicationContext.getBean(EduQuestionService.class).delete(id);
        } else {
            throw new IllegalArgumentException("类" + entity.getName() + "不支持批量删除操作");
        }
        return NORMAL;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    static DeleteWrapper NORMAL = new DeleteWrapper(1, null);

    static class DeleteWrapper {
        int count;
        String msg;
        int code;

        public DeleteWrapper(int count, String msg) {
            this.count = count;
            this.msg = msg;
        }

        public DeleteWrapper(int count, int code, String msg) {
            this.count = count;
            this.code = code;
            this.msg = msg;
        }
    }
}
